
#include <windows.h>


#include <gl/gl.h>
#include <gl/glu.h>
#include <math.h>

#include "tf_Camera.h"



TfCamera::TfCamera(void)
{
}

TfCamera::~TfCamera()
{
}

void TfCamera::Projection() 
{
	//switch to projection
   	glMatrixMode(GL_PROJECTION);
   	glLoadIdentity();

	glRenderMode(GL_RENDER);

	//apply projective matrix
	double left		=  - m_width/2.0;
	double right	=  m_width/2.0;
	double bottom	=  - m_height/2.0;
	double top		=  m_height/2.0;

	glOrtho(left,right,bottom,top,m_near,m_far);

	glMatrixMode( GL_MODELVIEW );
	glLoadIdentity( );
	gluLookAt(m_eye[0],m_eye[1],m_eye[2],m_ref[0],m_ref[1],m_ref[2],m_vecUp[0], m_vecUp[1], m_vecUp[2]);	
}

void TfCamera::Selection(int xPos,int yPos)
{
	GLint	vp[4];
	glGetIntegerv(GL_VIEWPORT,vp);

   	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
 
	glRenderMode(GL_SELECT);
 	gluPickMatrix(xPos,vp[3]-yPos, 1, 1, vp );

	//apply projective matrix
	double left		=  - m_width/2.0;
	double right	=  m_width/2.0;
	double bottom	=  - m_height/2.0;
	double top		=  m_height/2.0;

	glOrtho(left,right,bottom,top,m_near,m_far);
	
	glMatrixMode( GL_MODELVIEW );
	glLoadIdentity( );
	gluLookAt(m_eye[0],m_eye[1],m_eye[2],m_ref[0],m_ref[1],m_ref[2],m_vecUp[0], m_vecUp[1], m_vecUp[2]);
}

void TfCamera::Init()
{

	m_eye[0] = 0.0;
	m_eye[1] = 0.0;
	m_eye[2] = 1000.0;

	m_ref[0] = 0.0;
	m_ref[1] = 0.0;
	m_ref[2] = 0.0;

	m_far = 10000;
	m_near= 1;

	m_width = 2400.0;
	m_height = 2400.0;


	m_vecUp[0] = 0.0;
	m_vecUp[1] = 1.0;
	m_vecUp[2] = 0.0;


	m_screen[0] = 400;
	m_screen[1] = 400;



}

void TfCamera::SetScreen( int x, int y) 
{ 
	glViewport(0,0,x,y);
	if( y== 0) 
		y=1;
	double ratio = (double)x/(double)y;
	m_width *= (double)x/m_screen[0];
	m_height *= (double)y/m_screen[1];
	m_width =  m_height*ratio;
	m_screen[0] = x;
	m_screen[1] = y; 

}

void TfCamera::SetEye(double eye_x,double eye_y,double eye_z)
{
	m_eye[0] = eye_x;
	m_eye[1] = eye_y;
	m_eye[2] = eye_z;
}

void TfCamera::SetRef(double ref_x,double ref_y,double ref_z)
{
	m_ref[0] = ref_x;
	m_ref[1] = ref_y;
	m_ref[2] = ref_z;
}

void TfCamera::SetVecUp(double up_dx,double up_dy,double up_dz)
{
	m_vecUp[0] = up_dx;
	m_vecUp[1] = up_dy;
	m_vecUp[2] = up_dz;
}

void TfCamera::SetViewRect(double width,double height)
{
	m_width = width;
	m_height = height;
	double aspect = m_screen[0]/m_screen[1];
	m_width =  m_height*aspect;
}

void TfCamera::GetViewRect(double& width,double& height)
{
	width = m_width;
	height = m_height;
}

void TfCamera::Zoom(double scale)
{
	if (scale <= 0.0)
	{
		return;
	}
    m_width *= scale;
    m_height *= scale;
}

void TfCamera::ZoomAll(double x0,double y0,double z0,double x1,double y1,double z1)
{
	double width,height;
	double	xl, yl, zl;
	xl = x1-x0;
	yl = y1-y0;
	zl = z1-z0;

	width = max(max(xl,yl),zl);
	height= max(max(xl,yl),zl);

	SetViewRect(width,height);

	double vec[3];
	vec[0] = m_eye[0] - m_ref[0];
	vec[1] = m_eye[1] - m_ref[1];
	vec[2] = m_eye[2] - m_ref[2];
	m_ref[0] = (x0+x1)/2;
	m_ref[1] = (y0+y1)/2;
	m_ref[2] = (z0+z1)/2;
	m_eye[0] = m_ref[0] + vec[0];
	m_eye[1] = m_ref[1] + vec[1];
	m_eye[2] = m_ref[2] + vec[2];
}

void TfCamera::SetViewType( int type )
{
	int i;
	double r;
	double vec[3]; 

	for (i = 0;i < 3;i++)
	{
		vec[i] = m_ref[i] - m_eye[i];
	}
	
	r = sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);

	if(r <= 0 ) 
		r = 50.0;
	if( r > 10000) 
		r = 10000;

	switch(type)
	{
	case VIEW_FRONT:
		m_eye[0] = m_ref[0] +0.0;
		m_eye[1] = m_ref[1] +(-r);
		m_eye[2] = m_ref[2] +0.0;
		m_vecUp[0] = 0.0;
		m_vecUp[1] = 0.0;
		m_vecUp[2] = 0.0;
		break;

// 		m_eye = m_ref + CVector3D(0,-r,0);
// 		m_vecUp = CVector3D(0,0,1);
// 		break;
// 	case VIEW_BACK:
// 		m_eye = m_ref + CVector3D(0,r,0);
// 		m_vecUp = CVector3D(0,0,1);
// 		break;
// 	case VIEW_TOP:
// 		m_eye = m_ref + CVector3D(0,0,r);
// 		m_vecUp = CVector3D(0,1,0);
// 		break;
// 	case VIEW_BOTTOM:
// 		m_eye = m_ref + CVector3D(0,0,-r);
// 		m_vecUp = CVector3D(0,1,0);
// 		break;
// 	case VIEW_RIGHT:
// 		m_eye = m_ref + CVector3D(r,0,0);
// 		m_vecUp = CVector3D(0,0,1);
// 		break;
// 	case VIEW_LEFT:
// 		m_eye = m_ref + CVector3D(-r,0,0);
// 		m_vecUp = CVector3D(0,0,1);
// 		break;
// 	case VIEW_SW_ISOMETRIC:
// 		m_eye = m_ref + CVector3D(-1,-1,1).GetNormal()*r;
// 		update_upVec();		
// 		break;
// 	case VIEW_SE_ISOMETRIC:
// 		m_eye = m_ref + CVector3D(1,-1,1).GetNormal()*r;
// 		update_upVec();		
// 		break;
// 	case VIEW_NE_ISOMETRIC:
// 		m_eye = m_ref + CVector3D(1,1,1).GetNormal()*r;
// 		update_upVec();
// 		break;
// 	case VIEW_NW_ISOMETRIC:
// 		m_eye = m_ref + CVector3D(-1,1,1).GetNormal()*r;
// 		update_upVec();
// 		break;
	}
}

// void TfCamera::move_view(double dpx, double dpy)
// {
// 	CVector3D vec;
// 	CVector3D xUp, yUp;
// 
// 	vec = m_ref - m_eye;
// 	vec.Normalize();
// 	xUp = vec*m_vecUp;
// 	yUp = xUp*vec;
// 
// 	m_eye -= xUp*m_width*dpx + yUp*m_height*dpy;
// 	m_ref -= xUp*m_width*dpx + yUp*m_height*dpy;
// }

// void TfCamera::update_upVec()
// {
// 	CVector3D vec = m_ref - m_eye;
// 	CVector3D zVec(0,0,1);
// 	CVector3D vec0;
// 
// 	vec.Normalize();
// 	vec0 = vec*zVec; 
// 	m_vecUp = vec0*vec;
// }
